/*
 *  Copyright 2005 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.webapp.util.forum;

import com.blandware.atleap.common.ForumModuleConstants;
import com.blandware.atleap.common.util.StringUtil;
import com.blandware.atleap.model.core.User;
import com.blandware.atleap.model.core.Role;
import com.blandware.atleap.model.forum.Forum;
import com.blandware.atleap.model.forum.ForumSubscription;
import com.blandware.atleap.model.forum.Post;
import com.blandware.atleap.model.forum.Topic;
import com.blandware.atleap.service.forum.ForumManager;
import com.blandware.atleap.service.util.MailEngine;
import com.blandware.atleap.webapp.util.core.GlobalProperties;
import com.blandware.atleap.webapp.util.core.WebappUtil;
import org.apache.struts.action.ActionForward;
import org.apache.struts.util.RequestUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.MalformedURLException;
import java.util.*;
import java.lang.reflect.InvocationTargetException;

/**
 * <p>Contains utilities used in web-layer of forum module.</p>
 * <p><a href="ForumModuleWebUtil.java.html"><i>View source</i></a></p>
 *
 * @author Roman Puchkovskiy <a href="mailto:roman.puchkovskiy@blandware.com">
 *         &lt;roman.puchkovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.5 $ $Date: 2006/11/30 10:44:17 $
 */
public class ForumModuleWebUtil {

    /**
     * Returns URI which corresponds to a given forum.
     *
     * @param forum forum which URI is obtained
     * @return forum URI
     */
    public static String getForumUri(Forum forum) {
        return forum.getUri();
    }

    /**
     * Returns URI which corresponds to a given topic.
     *
     * @param topic topic which URI is obtained
     * @return topic URI
     */
    public static String getTopicUri(Topic topic) {
        return ForumModuleWebConstants.FORUM_URI_PREFIX +
                ForumModuleWebConstants.TOPIC_URI_PREFIX + topic.getId();
    }

    /**
     * Returns URI which corresponds to a given post.
     *
     * @param post post which URI is obtained
     * @return post URI
     */
    public static String getPostUri(Post post) {
        return post.getUri();
    }

    /**
     * Sends messages via email to addresses which are subscribed to forum or
     * topic corresponding to a given post.
     *
     * @param post post which was just created
     * @param forumManager forum manager
     * @param mailEngine mail engine used to send mail
     * @param deleteSubscriptionForward forward for deletion of subscription
     * @param request request we are serving
     * @param response response we are creating
     */
    public static void sendTrackMessages(Post post, ForumManager forumManager,
                                         MailEngine mailEngine,
                                         ActionForward deleteSubscriptionForward,
                                         HttpServletRequest request,
                                         HttpServletResponse response) {

        Topic topic = post.getTopic();
        Forum forum = forumManager.retrieveForum(topic.getForum().getId());

        List roles = forum.getRoles();
        List forumRoleNames = new ArrayList();
        for (Iterator i = roles.iterator(); i.hasNext(); ) {
            Role role = (Role) i.next();
            forumRoleNames.add(role.getName());
        }

        String localeIdentifier = (RequestUtils.getUserLocale(request, null)).getLanguage();

        Map model = new HashMap();
        String postUri = getPostUri(post);

        StringBuffer postUrlBuffer = null;
        String postUrl = null;
        try {
            postUri = WebappUtil.computeURL(postUri, null, null, null, null, request, response, false, false);
            postUrlBuffer = RequestUtils.createServerUriStringBuffer(request.getScheme(), request.getServerName(), request.getServerPort(), postUri);
            postUrl = postUrlBuffer.toString();
        } catch (MalformedURLException e) {
            postUrl = "";
        }

        model.put("forumTitle", forum.getSingleTitle());
        model.put("topicSubject", topic.getFirstPostSubject());
        model.put("author", post.getAuthor());
        model.put("subject", post.getSubject());
        model.put("body", post.getBody());
        model.put("url", postUrl);

        // body will not be encoded
        Set exceptions = new HashSet();
        exceptions.add("body");

        Set servedAddresses = new HashSet();
        String fromAddress = GlobalProperties.getInstance(request.getSession().getServletContext()).getString(ForumModuleConstants.FORUM_FROM_ADDRESS);
        List subscriptions = forumManager.findActivatedSubscriptionsByForumIdOrTopicId(forum.getId(), topic.getId());

        if (subscriptions != null) {
            for (Iterator i = subscriptions.iterator(); i.hasNext(); ) {
                ForumSubscription subscription = (ForumSubscription) i.next();
                User user = subscription.getUser();
                boolean anonymous = user == null;

                boolean isAllowed;
                if (anonymous) {
                    isAllowed = roles == null || roles.isEmpty();
                } else {
                    if (forumRoleNames.isEmpty()) {
                        isAllowed = true;
                    } else {
                        List userRoleNames = new ArrayList();
                        for (Iterator j = user.getRoles().iterator(); j.hasNext(); ) {
                            Role role = (Role) j.next();
                            userRoleNames.add(role.getName());
                        }
                        List tempForumRoleNames = new ArrayList(forumRoleNames);
                        tempForumRoleNames.removeAll(userRoleNames);
                        isAllowed = tempForumRoleNames.isEmpty();
                    }
                }

                if (isAllowed) {
                    String contactAddress = !anonymous ? user.getEmail() : subscription.getEmail();
                    if (servedAddresses.contains(contactAddress)) {
                        // skip this address because it was already served
                        continue;
                    }

                    String unsubscribeUrl = null;
                    if (anonymous) {
                        Map parameters = new HashMap();
                        parameters.put("id", subscription.getId());
                        parameters.put("token", subscription.getToken());
                        try {
                            String unsubscribeUri = WebappUtil.computeURL(deleteSubscriptionForward.getPath(), null, null, null, parameters, request, response, false, false);
                            StringBuffer unsubscribeUrlBuffer = RequestUtils.createServerUriStringBuffer(request.getScheme(), request.getServerName(), request.getServerPort(), unsubscribeUri);
                            unsubscribeUrl = unsubscribeUrlBuffer.toString();
                        } catch (MalformedURLException e) {
                            unsubscribeUrl = "";
                        }
                    } else {
                        unsubscribeUrl = postUrl;
                    }

                    model.put("unsubscribeUrl", unsubscribeUrl);

                    Map encodedModel = StringUtil.htmlEncodeModelWithExceptions(model, exceptions);

                    // send message
                    try {
                        mailEngine.sendMessage(fromAddress, null, new String[]{contactAddress}, null, null, "forumSubscription", localeIdentifier, encodedModel, false);
                    } catch (Exception e) {
                    }
                    servedAddresses.add(contactAddress);
                }
            }
        }
    }

    /**
     * Wraps body of replied post (for quoting).
     *
     * @param body body to wrap
     * @return wrapped body
     */
    public static String wrapRepliedPostBody(String body) {
        if (body == null) {
            body = "";
        }
        return "<em>" + body + "</em><br><br>";
    }

    /**
     * Returns a list of a forum and all its ancestors; list is ordered from
     * ancestor to descendant.
     *
     * @param forum forum which ancestors to retrieve
     * @param forumManager forum manager used to retrieve forums
     * @return list of ancestors including given forum
     */
    public static List getForumParentsList(Forum forum, ForumManager forumManager) {
        List parentsList = new ArrayList();
        parentsList.add(forum);
        Forum currentParent = forum.getParent();
        while (currentParent != null) {
            parentsList.add(forumManager.retrieveForum(currentParent.getId()));
            currentParent = currentParent.getParent();
        }
        Collections.reverse(parentsList);
        return parentsList;
    }
}
